package org.fly.utils.code;
import org.apache.commons.lang.StringUtils;
import org.fly.bean.*;

import java.io.FileOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by rongzhao.zhu on 2018/1/22.
 */
public class CodeAuto {


    public static String base_path="D:/self/sps/src/main/";
    public static final String src_base_path=base_path+"java/";
    public static final String mapper_path =base_path+"/resources/mappers/";
    public static  String controller_prefix="Admin";

    public static final String p_sep =".";

    private static String TABLE_PREFIX = "t";
    private static String Mapper_PreFix = "t";

    public static String base_package ="";
    public static final String query_vm = "vm/query.vm";
    public static final String dao_vm="vm/dao.vm";
    public static final String service_vm="vm/service.vm";
    public static final String service_impl_vm="vm/serviceImpl.vm";
    public static final String controller_vm = "vm/controller.vm";
    public static final String mapper_vm = "vm/mapper.vm";

    public static String parent_package =  CodeAuto.class.getPackage().getName();
    public static String query_bean_package ;
    public static String dao_package ;
    public static String service_package ;
    public static String service_impl_package;
    public static String controller_package;
    public static Class clazz;

    public static String author = "fly";
    public static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    static {
        base_package = parent_package.replace(".utils.code","");
        query_bean_package = base_package+".bean.query";
        dao_package = base_package+".dao";
        service_package = base_package+".service";
        service_impl_package = base_package +".service.impl";

    }
    public static void main(String[] args){
        base_path="D:/self/sps/src/main/";
        clazz = SmsTemplate.class;
        author = "autoCode";
        controller_prefix="Admin";
        controller_package = base_package+".controller."+instanceName(controller_prefix);
        buildMapper();
        buildQueryBean();
        buildDao();
        buildService();
        buildServiceImpl();
        buildController();
    }

    /**
     * 构建vm文件所需要的参数
     * @return
     */
    private static Map<String,Object> buildParamMap(){
        Map<String,Object> map = new HashMap<>();
        String queryBeanName = getQueryBeanName();
        String queryBeanAllName = query_bean_package+p_sep+queryBeanName;
        String daoName = getDaoName();
        String serviceName = getServiceName();
        String serviceImplName = getServiceImplName();
        String controllerName = getControllerName();
        //作者
        map.put("author",author);
        map.put("time",format.format(new Date()));

        map.put("bean_name",clazz.getSimpleName());
        map.put("bean_instance_name",instanceName(clazz.getSimpleName()));
        map.put("bean_all_name",clazz.getCanonicalName());
        //query Bean
        map.put("query_bean_package",query_bean_package);
        map.put("query_bean_name",queryBeanName);
        map.put("query_bean_all_name",queryBeanAllName);
        //dao interface
        map.put("dao_package",dao_package);
        map.put("dao_name",daoName);
        map.put("dao_all_name",dao_package+p_sep+daoName);
        map.put("dao_instance_name",instanceName(daoName));

        //service interface
        map.put("service_package",service_package);
        map.put("service_name",serviceName);
        map.put("service_all_name",service_package+p_sep+serviceName);
        map.put("service_instance_name",instanceName(serviceName));

        //service class
        map.put("service_impl_package",service_impl_package);
        map.put("service_impl_name",serviceImplName);
        map.put("service_impl_all_name",service_impl_package+p_sep+serviceImplName);
        //controller class
        map.put("controller_package",controller_package);
        map.put("controller_name",controllerName);
        map.put("controller_all_name",controller_package+p_sep+controllerName);
        map.put("base_controller_url","/"+instanceName(controller_prefix)+"/"+instanceName(clazz.getSimpleName())+"/");

        return  map;
    }
    private static String getBeanName(){
        String beanName =clazz.getSimpleName();
        return beanName;
    }
    private static String getQueryBeanName(){
       return getBeanName()+"Query";
    }
    private static String getDaoName(){
        return getBeanName()+"Dao";
    }
    private static String getServiceName(){
        return getBeanName()+"Service";
    }
    private static String getServiceImplName(){
        return getBeanName()+"ServiceImpl";
    }
    private static String getControllerName(){

        return controller_prefix+getBeanName()+"Controller";
    }




    /**
     * 创建queryBean
     */
    public static void buildQueryBean(){
        Field[] fields =  clazz.getDeclaredFields();
        List<Map> fieldMap = Arrays.stream(fields).filter(f->f.getAnnotation(QueryField.class)!=null).map(f->{
            QueryField queryField =  f.getAnnotation(QueryField.class);
            Class fType = f.getType();
            String fTypeStr = fType.getSimpleName();
            String queryName = queryField.name();
            if(StringUtils.isBlank(queryName)){
                queryName = f.getName();
            }
            Map<String,String> filedMap = new HashMap<>();
            filedMap.put("name",queryName);
            filedMap.put("type",fTypeStr);
            filedMap.put("UpName",className(queryName));
            return filedMap;
        }).collect(Collectors.toList());
        Map<String,Object> map = buildParamMap();
        map.put("feilds",fieldMap);
        try{
            String  fileContent = VelocityUtil.getRenderResult(query_vm,map);
            System.out.println(fileContent);
            String queryBeanAllName = (String) map.get("query_bean_all_name");
            createFile(src_base_path+package2File(queryBeanAllName),fileContent);
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    public static void buildDao(){
        Map<String,Object> map = buildParamMap();
        try{
            String  fileContent = VelocityUtil.getRenderResult(dao_vm,map);
            System.out.println(fileContent);
            String daoAllName = (String) map.get("dao_all_name");
            createFile(src_base_path+package2File(daoAllName),fileContent);
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    public static void buildService(){
        Map<String,Object> map = buildParamMap();
        try{
            String  fileContent = VelocityUtil.getRenderResult(service_vm,map);
            System.out.println(fileContent);
            String serviceAllName = (String) map.get("service_all_name");
            createFile(src_base_path+package2File(serviceAllName),fileContent);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    public static void buildServiceImpl(){
        Map<String,Object> map = buildParamMap();
        try{
            String  fileContent = VelocityUtil.getRenderResult(service_impl_vm,map);
            System.out.println(fileContent);
            String serviceAllName = (String) map.get("service_impl_all_name");
            createFile(src_base_path+package2File(serviceAllName),fileContent);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    public static void buildController(){
        Map<String,Object> map = buildParamMap();
        try{
            String  fileContent = VelocityUtil.getRenderResult(controller_vm,map);
            System.out.println(fileContent);
            String controllerAllName = (String) map.get("controller_all_name");
            createFile(src_base_path+package2File(controllerAllName),fileContent);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void buildMapper(){
        Field[] fields =  clazz.getDeclaredFields();
        List<Map> fieldMap = Arrays.stream(fields).map(f->{
            Class fType = f.getType();
            String fTypeStr = fType.getSimpleName();
            String queryName = f.getName();

            Map<String,String> filedMap = new HashMap<>();
            filedMap.put("name",queryName);
            filedMap.put("type",fTypeStr);
            filedMap.put("column",getColumnName(queryName));
            return filedMap;
        }).collect(Collectors.toList());

        List<Map> queryMap = Arrays.stream(fields).filter(f->f.getAnnotation(QueryField.class)!=null).map(f->{
            QueryField queryField =  f.getAnnotation(QueryField.class);
            Class fType = f.getType();
            String fTypeStr = fType.getSimpleName();
            String queryName = queryField.name();
            if(StringUtils.isBlank(queryName)){
                queryName = f.getName();
            }
            Map<String,String> filedMap = new HashMap<>();
            filedMap.put("name",queryName);
            filedMap.put("type",fTypeStr);
            filedMap.put("oper",queryField.oper().name());
            filedMap.put("column",getColumnName(queryName));
            return filedMap;
        }).collect(Collectors.toList());
        Map<String,Object> map = buildParamMap();
        map.put("feilds",fieldMap);
        map.put("queryFeilds",queryMap);
        map.put("table_name",getTableName(clazz.getSimpleName()));
        try{
            String  fileContent = VelocityUtil.getRenderResult(mapper_vm,map);
            System.out.println(fileContent);
            createFile(mapper_path+getTableName(clazz.getSimpleName())+".xml",fileContent);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private static void createFile(String path,String content){
        try{

            OutputStream out = new FileOutputStream(path);
            out.write(content.getBytes());
            out.flush();
            out.close();
        }catch (Exception e){
            e.printStackTrace();
        }

    }
    private static String package2File(String allName){
      return   allName.replaceAll("\\.", "\\\\")+"."+"java";
    }



    private static String className(String name) {
        char[] cs=name.toCharArray();
        if(cs[0]>=97&&cs[0]<=122){
            cs[0]-=32;
        }
        return String.valueOf(cs);

    }
    private static String columnName(String name) {
        char[] cs=name.toCharArray();
        if(cs[0]>=97&&cs[0]<=122){
            cs[0]-=32;
        }
        return String.valueOf(cs);

    }
    private static String instanceName(String name) {
        char[] cs=name.toCharArray();
        if(cs[0]>=65&&cs[0]<=90){
            cs[0]+=32;
        }
        return String.valueOf(cs);

    }


    private static String getSQLName(String name, String pre) {
        char[] nameArray = name.toCharArray();
        StringBuffer buffer = new StringBuffer(pre);
        buffer.append("_");
        int i;
        for (i = 0; i < nameArray.length; i++) {
            if (nameArray[i] <= 'Z' && nameArray[i] >= 'A') {
                if (i != 0) {
                    buffer.append("_");
                }
                buffer.append(String.valueOf(nameArray[i]).toLowerCase());
            } else {
                buffer.append(nameArray[i]);
            }
        }
        String result = buffer.toString();
        buffer.setLength(0);
        return result;
    }

    public static String getTableName(String className) {
        return getSQLName(className, Mapper_PreFix);
    }


    public static String getColumnName(String fieldName) {
        return getSQLName(fieldName, "f");
    }



}
